﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bystd.DbFactory
{
    using DbSqlProvider.SqlKeywords;
    using DbSqlProvider.SqlFunctions;

    public class SqlProvider : ISqlProvider
    {
        public FactoryType DbType { get; set; }

        public SqlProvider(FactoryType dbType = FactoryType.PostgreSQL)
        {
            this.DbType = dbType;
        }

        public static ISqlProvider CreateProvider(FactoryType dbType = FactoryType.PostgreSQL)
        {
            return new SqlProvider(dbType);
        }

        public Select Select(params string[] columns)
        {
            Select _select = new Select(columns);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Select<T> Select<T>() where T : class
        {
            Select<T> _select = new Select<T>();
            _select.SqlString = _select.ToString();
            return _select;
        }
        public Select<T> Select<T, R>(Func<T, R> selector) where T : class
        {
            Select<T> _select = new Select<T>();
            _select.SqlString = _select.ToString(selector);
            return _select;
        }
        public Select<T> Select<T>(Max input) where T : class
        {
            Select<T> _select = new Select<T>(input);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Select<T> Select<T>(Min input) where T : class
        {
            Select<T> _select = new Select<T>(input);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Select<T> Select<T>(Avg input) where T : class
        {
            Select<T> _select = new Select<T>(input);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Select<T> Select<T>(Count input) where T : class
        {
            Select<T> _select = new Select<T>(input);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Select<T> Select<T>(Sum input) where T : class
        {
            Select<T> _select = new Select<T>(input);
            _select.SqlString = _select.ToString();
            return _select;
        }

        public Insert<T> Insert<T>() where T : class
        {
            Insert<T> insert = new Insert<T>();
            insert.SqlString = insert.ToString();

            return insert;
        }

        public Insert Insert(string tableName)
        {
            Insert insert = new Insert(tableName);
            insert.SqlString = insert.ToString();

            return insert;
        }

        public Update Update(string tableName)
        {
            Update up = new Update();
            up.SqlString = up.ToString(tableName);
            return up;
        }

        public Update<T> Update<T>() where T : class
        {
            Update<T> up = new Update<T>();
            up.SqlString = up.ToString();
            return up;
        }

        public Delete Delete()
        {
            Delete delete = new Delete();
            delete.SqlString = delete.ToString();

            return delete;
        }
        public Select<T> Select<T>(Func<T, dynamic> selector) where T : class
        {
            Select<T> _select = new Select<T>();
            _select.SqlString = _select.ToString(selector);
            return _select;
        }

        public Select<T> Select<T>(Func<T, dynamic> selector, IFunction[] functions) where T : class
        {
            Select<T> _select = new Select<T>();
            _select.SqlString = _select.ToString(selector);

            if (functions != null && functions.Length > 0)
            {
                List<string> funList = new List<string>(functions.Length);
                foreach (var fun in functions) funList.Add(fun.ToString());

                _select.SqlString += "," + string.Join(",", funList);
            }

            return _select;
        }
    }
}
